/*
 * @Author: 13938960424 1758142861@qq.com
 * @Date: 2023-10-31 14:14:41
 * @LastEditors: 13938960424 1758142861@qq.com
 * @LastEditTime: 2023-10-31 15:31:40
 * @FilePath: /sjf/new-xshell/muduo/source/eventloop.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once

#include <iostream>
#include <thread>
#include <memory>
#include <unistd.h>
#include <fcntl.h>
#include <mutex>
#include <sys/eventfd.h>
#include "channel.hpp"

using Functor = std::function<void()>;
class Channel;
class EventLoop
{
public:
    EventLoop()
    :_thread_id(std::this_thread::get_id())
    ,_event_fd(CreateEventFd())
    ,_event_channel(new Channel(_event_fd,_poller))
    {
        //给eventfd添加可读事件回调函数,读取eventfd事件通知次数
        _event_channel->SetReadCallback(&EventLoop::ReadEventFd,this);
        //启动eventfd的读事件监控
        _event_channel->EnableRead();
    }
    //判断将要执行的任务是否处于当前线程,如果存在则执行,不是则压入队列
    void RunInLoop(const Functor& cb)
    {
        if(IsInLoop(cb))
            return cb();
        return QueueLoop(cb);
    }
    //将任务压入任务池
    void QueueLoop(const Functor& cb)
    {
        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _tasks.push_back(cb);  
        }
        //需要唤醒有可能因为没有事件就绪,而导致epoll阻塞
        WeakUpEventFd();
    }
    //用于判断当前线程是否是EventLoop对应的线程
    bool IsInLoop() { return _thread_id == std::this_thread::get_id(); }
    //增加/修改描述符事件监控
    void UpdateEvent(Channel* channel) { return _poller.UpdateEvent(channel); }
    //移除描述符事件监控
    void RemoveEvent(Channel* channel) { return _poller.RemoveEvent(channel); }
    //开始--事件监控,就绪事件处理,执行任务
    void Start()
    {
        //1.开始监控
        std::vector<Channel*> actives;
        _poller.Poll(actives);
        //2.事件处理
        for(auto& e : actives)
        {
            e->HandleEvent();
        }
        //3.执行任务
        RunAllTask();
    }
public:
    //执行任务池中的所有任务
    void RunAllTask()
    {
        std::vector<Functor> functor;
        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _tasks.swap(functor);
        }
        for(auto &f: functor) { f(); }
        return ;
    }
    static int CreateEventFd()
    {
        int efd = eventfd(0,EFD_CLOEXEC | EFD_NONBLOCK);
        if(efd < 0)
        {
            ERR_LOG("create eventfd error");
            abort();
        }
        return efd;
    }
    void ReadEventFd()
    {
        uint64_t res = 0;
        int ret = read(_event_fd,&res,sizeof(res));
        if(ret < 0)
        {
            if(errno == EINTR || errno == EAGAIN) { return; }
            ERR_LOG("read eventfd error!");
            abort();
        }
        return ;
    }
    void WeakUpEventFd()
    {
        uint64_t val = 1;
        int ret = write(_event_fd,&val,sizeof(val));
        if(ret < 0)
        {
            if(errno == EINTR || errno == EAGAIN) { return; }
            ERR_LOG("read eventfd error!");
            abort();
        }
        return ;
    }
private:
    std::thread::id _thread_id;//线程ID
    int _event_fd;//eventfd唤醒IO事件监控id
    //Channel *_event_channel;
    std::unique_ptr<Channel> _event_channel;
    Poller _poller;//是所有描述符的事件监控
    std::vector<Functor> _tasks;//任务池
    std::mutex _mutex;//锁
};